package com.haust.search.dao.impl;

import com.haust.search.dao.SearchDao;
import com.haust.search.pojo.SearchItem;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Repository
public class SearchDaoImpl implements SearchDao {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 创建索引
     */
    @Override
    public void createIndex() {
        elasticsearchRestTemplate.indexOps(SearchItem.class).create();
    }

    /**
     * 设置映射
     */
    @Override
    public void putMapping() {
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(SearchItem.class);
        indexOperations.putMapping(
                indexOperations.createMapping()
        );
    }

    /**
     * 批量保存
     *
     * @param items
     */
    @Override
    public void batchSave(Iterable<SearchItem> items) {
        elasticsearchRestTemplate.save(items);
    }

    @Override
    public Map<String, Object> search(String q, Integer page, Integer rows) {

        //搜索条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(
                QueryBuilders.matchQuery("title", q)
        ).should(
                QueryBuilders.matchQuery("sellPoint", q)
        ).should(
                QueryBuilders.matchQuery("categoryName", q)
        );

        HighlightBuilder.Field titleField = new HighlightBuilder.Field("title");
        titleField.preTags("<span style='color:red'>")
                .postTags("</span>");

        HighlightBuilder.Field sellPointField = new HighlightBuilder.Field("sellPoint");
        sellPointField.preTags("<span style='color:red'>")
                .postTags("</span>");

        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder) //搜索条件
                .withPageable(PageRequest.of(page - 1, rows)) //分页条件
                .withHighlightFields(titleField, sellPointField) //高亮字段
                .build();

        SearchHits<SearchItem> hits = elasticsearchRestTemplate.search(query, SearchItem.class);

        //处理搜索结果
        ArrayList<SearchItem> list = new ArrayList<SearchItem>();

        for (SearchHit<SearchItem> hit : hits) {
            //得到整体内容
            SearchItem searchItem = hit.getContent();

            //判断是否是 高亮字段
            List<String> titleHl = hit.getHighlightField("title");
            if (titleHl != null && titleHl.size() != 0) {
                //说明有 title的高亮
                searchItem.setTitle(titleHl.get(0));
            }

            List<String> sellPointHi = hit.getHighlightField("sellPoint");
            if (sellPointHi != null && sellPointHi.size() != 0) {
                //说明 sellPoint 有高亮字段
                searchItem.setSellPoint(sellPointHi.get(0));
            }

            list.add(searchItem);
        }

        //维护返回结果
        HashMap<String, Object> result = new HashMap<>();
        result.put("total", list.size());
        result.put("list", list);
        result.put("rows", rows);
        result.put("page", page);

        return result;
    }

    /**
     * 删除 对应 ES中的商品
     * @param itemId 商品id
     */
    @Override
    public void removeById(Long itemId) {
        elasticsearchRestTemplate.delete(itemId.toString(),SearchItem.class);
    }

    /**
     * 向es中添加商品
     * @param searchItem 商品信息
     */
    @Override
    public void save(SearchItem searchItem) {
        elasticsearchRestTemplate.save(searchItem);
    }
}
